Unix网络编程-第2章 传输层:TCP、UDP和SCTP

2.1 概述

本章的目的:从网络编程角度提供足够的细节以理解如何使用这些协议,同时提供有关这些协议的实际设计、实现及历史的具体描述的参考点。

UDP:一个简单、不可靠的数据报协议

TCP:一个复杂、可靠的字节流协议

SCTP:一个可靠的传输协议,提供消息边界、传输级别多宿支持以及将头端阻塞减少到最小的一种方法

2.2 总图

2.1

IPv4:网际协议版本4,使用32位ip地址

IPv6:网际协议版本6,使用128位ip地址

TCP:传输控制协议,是一个面向连接的协议,为用户提供可靠的全双工字节流。TCP套接字是一种流套接字

UDP:用户数据报协议,是一个无连接协议。UDP套接字是一种数据报套接字

SCTP:流控制传输协议,提供可靠全双工关联的面向连接的协议

ICMP:网际控制消息协议,处理在路由器和主机之间流通的错误和控制信息

IGMP:网际组管理协议,用于多播

ARP:地址解析协议,把一个IPv4地址映射成一个硬件地址

RARP:反向地址解析协议,把一个硬件地址映射成一个IPv4地址

ICMPv6:网际控制消息协议版本6,综合了ICMPv4、IGMP和ARP的功能

BPF:BSD分组过滤器,该接口提供对于数据链路层的访问能力

DLPI:数据链路提供者接口,该接口提供对于数据链路层的访问能力

2.3 用户数据报协议(UDP)

每个UDP数据报都有一个长度。如果一个数据报正确地到达其目的地,那么该数据报的长度将随数据一道传递给接收端应用进程。

UDP可以是全双工的。

2.4 传输控制协议(TCP)

TCP客户先与某个给定服务器建立一个连接,再跨该连接与那个服务器交换数据,然后终止这个连接。

TCP提供了可靠性:接收确认、超时、重传等机制

TCP含有动态估算客户和服务器之间的往返时间的算法(RTT),以便知道等待一个确认需要多长时间。

TCP通过给每个字节关联一个序列号对所发送的数据进行排序。

TCP提供流量控制,告知对端它一次能够从对端接收多少字节的数据,称为通告窗口

TCP连接是全双工的,TCP必须为每个数据流方向跟踪状态信息(序列号、通告窗口大小等)。

2.5 流控制传输协议(SCTP)

SCTP在客户和服务器之间提供关联,并向TCP那样提供可靠性、排序、流量控制以及全双工的数据传送。

关联与连接

  1. 一个连接只涉及两个IP地址之间的通信
  2. 一个关联指代两个系统之间的一次通信

SCTP因为支持多宿而涉及不止两个地址,因而使用关联。

SCTP是面向消息的,提供各个记录的按序递送服务,由发送端写入的每条记录的长度随数据一道传递给接收端应用。

SCTP能够在所连接的端点之间提供多个流,每个流各自可靠地按序递送消息,一个流上的某个消息的丢失不会阻塞同一关联其他流上消息的投递。

TCP在单一字节流中任何位置的字节丢失都将阻塞该连接上其后所有数据的递送,直到该丢失被修复为止。

SCTP提供多宿特性,使得单个SCTP端点能够支持多个IP地址。该特性可以增强应对网络故障的健壮性。

2.6 TCP连接的建立和终止

连接:三次握手

  1. 服务器准备好接受外来的连接。通常调用socket、bind和listen这3个函数完成,称为被动打开

  2. 客户通过connect发起主动打开,导致客户TCP发送一个SYN(同步)分节(包含客户发送数据的初始序列号)

  3. 服务器确认(ACK)客户的SYN,同时发送一个SYN分节(包含服务器发送数据的初始序列号)。服务器在单个分节中发送SYN和ACK

  4. 客户确认服务器的SYN

image-20200603104007120

客户的初始序列号为J,服务器的初始序列号为K

TCP选项

每个SYN可以含有多个TCP选项,常用选项如下:

  1. MSS选项,发送SYN的TCP一端使用本选项通告它的最大分节大小(MSS),表示在本连接每个TCP分节中愿意接受的最大数据量。发送端TCP使用接收端的MSS值作为发送分节的最大大小。
  2. 窗口规模选项,即窗口扩大选项,TCP连接任何一端能够通告对端的最大窗口大小是65535,因为在TCP首部中相应的字段占16位。这个新选项指定TCP首部中的通告窗口必须扩大(即左移)的位数(0~14),因此提供的最大窗口接近1GB(65535 $\times$ $2^{14}$)。【必须两个端系统都支持才能使用】
  3. 时间戳选项,可以防止由失而复现的分组可能造成的数据损坏。【必须两个端系统都支持才能使用】

TCP连接终止

  1. 某个应用进程首先调用close,执行主动关闭,该端的TCP发送一个FIN分节,表示数据发送完毕
  2. 接收到FIN的对端执行被动关闭,FIN由TCP确认(ACK),它的接收也作为一个文件结束符(EOF)传递给接收端应用进程
  3. 一段时间后,接收到EOF的应用进程将调用close关闭套接字,TCP也发送一个FIN
  4. 接收最终FIN的原发送端TCP确认这个FIN(ACK)

步骤2和3发送都出自被动关闭一端,可能被合并成一个分节

image-20200603110023257

TCP状态转换图

image-20200806231516055

image-20200603110518695

分组交换图

image-20200806231656389

image-20200603110704379

服务器对客户请求的确认是伴随其应答发送的,这种做法称为捎带,通常在服务器处理请求并产生应答的时间少于200ms时发生。

2.7 TIME_WAIT状态

执行主动关闭的端点需要经历TIME_WAIT状态,该端点停留在这个状态的持续时间是最长分节生命期(MSL)的2倍,有时候称为2MSL

任何TCP实现都必须为MSL选择一个值,MSL是任何IP数据报能够在因特网中存活的最长时间。

每个数据报含有一个称为跳限的8位字段,最大值为255。

具有最大跳限(255)的分组在网络中存在的时间不可能超过MSL秒。

TIME_WAIT状态有两个存在的理由:

  1. 可靠地实现TCP全双工连接的终止

    最终的ACK可能丢失,有足够时间重传FIN+ACK,接收到重传后刷新TIME_WAIT的计数器

  2. 允许老的重复分节在网络中消逝

    防止旧连接的重复分组被新连接接收

2.8 SCTP关联的建立和终止

四路握手:

  1. 服务器准备好接受外来的关联,通过调用socket、bind和listen函数完成,称为被动打开
  2. 客户通过调用connect或者发送一个隐式打开该关联的消息进行主动打开,使得客户SCTP发送一个INIT消息(初始化),该消息告诉服务器客户的IP地址清单、初始序列号、用于标识本关联中所有分组的起始标记、客户请求的外出流的数目以及客户能够支持的外来流的数目。
  3. 服务器以一个INIT ACK消息确认客户的INIT消息,其中含有和客户INIT一样的属性消息以及一个状态cookie
  4. 客户以一个COOKIE ECHO消息回射服务器的状态cookie
  5. 服务器以一个COOKIE ACK消息确认客户回射的cookie是正确的,本关联于是建立

步骤4和5可能捆绑了用户数据

四路握手过程结束时,两端各自选择一个主目的地址,当不存在网络故障时,主目的地址将用作数据要发送到的默认目的地址。

image-20200603115544233

在关联的有效期内,验证标记Ta、Tz必须出现在对端发送的每个分组中出现。

cookie包含设置本SCTP关联所需的所有状态,服务器的SCTP栈就不必保存所关联客户的有关信息。

关联终止

SCTP不像TCP那样允许“半关闭”的关联,当一端关闭某个关联时,另一端必须停止发送新的数据,如果另一端有已经排队的数据,则发送完后完成关联关闭。

SCTP没有TIME_WAIT状态,因为SCTP使用了验证标记。

image-20200603152055341

SCTP状态转换图

image-20200806231816959

image-20200603152253351

分组交换过程

image-20200806231945414

image-20200603152326277

SCTP分组中信息的单位称为块(chunk)

2.9 端口号

TCP、UDP和SCTP都使用16位整数的端口号来区分进程。

TCP、UDP和SCTP定义了一组众所周知的端口,用于标识众所周知的服务

客户通常使用短期存活的临时端口,通常由传输层协议赋予客户,传输协议确保端口的唯一性。

端口号分为三段

  1. 众所周知的端口为0~1023,由IANA分配和控制
  2. 已登记的端口为1024~49151,不受IANA控制,不过由IANA登记并提供它们的使用情况清单
  3. 49152~65535是动态的或私用的端口,即临时端口,IANA不管。

注意事项:

  1. Unix系统有保留端口的概念,指的是小于1024的任何端口,使用这些端口需要root特权启动
  2. 有些系统的临时端口范围可能更大
  3. 少数客户需要一个保留端口用户客户/服务器的认证

套接字对

一个TCP连接的套接字对是一个定义该连接的两个端点的四元组:本地IP地址、本地TCP端口号、外地IP地址、外地TCP端口号。

套接字对唯一标识一个网络上的每个TCP连接。

标识每个端点的两个值(IP地址和TCP端口号)通常称为一个套接字

2.10 TCP端口号与并发服务器

TCP无法仅仅通过查看目的端口号来分离外来的分节到不同的端点,必须查看套接字对的所有四个元素才能确定由哪个端点来接收某个到达的分节。

2.11 缓冲区大小及限制

  • IPv4数据报的最大大小是65535字节,包括20字节的IPv4首部。
  • IPv6数据报的最大大小是65575字节,包括40字节的Ipv6首部。
  • 许多网络有一个由硬件规定的MTU。以太网的MTU为1500字节。
  • 在两个主机之间的路径中最小的MTU称为路径MTU。
  • 当一个IP数据报大小超过相应链路的MTU,IPv4和IPv6都将执行分片。
    • IPv4:主机对其产生的数据报执行分片,路由器对其转发的数据报执行分片
    • IPv6:主机对其产生的数据报执行分片,路由器不对转发的数据报执行分片
    • 分片到达最终目的地之前通常不会被重组
  • IPv4首部的“不分片”位(DF)如果被设置,则发送数据报的主机和转发它们的路由器都不允许对它们分片
  • IPv4和IPv6都定义了最小重组缓冲区大小,它是IPv4或IPv6的任何实现都必须保证支持的最小数据报大小。其值对于IPv4来说是576字节,对于IPv6为1500字节。
  • TCP有一个最大分节大小(MSS),用于向对端TCP通过对端在每个分节中能够发送的最大TCP数据量。
    • MSS的目的是告诉对端其重组缓冲区大小的实际值,从而试图避免分片
    • SYN分节上的MSS选项占16位,最大值为65535,IPv4数据报中的最大TCP数据量为65495(65535减去IPv4首部20字节和TCP首部20字节)
    • MSS经常设置为:$MSS=MTU-IP首部固定长度-TCP首部固定长度$
    • 以太网中使用IPv4的MSS值为1460,使用IPv6的MSS值为1440
  • SCTP基于到对端所有地址发现的最小路径MTU保持一个分片点

TCP输出

image-20200603171709141

UDP输出

image-20200603171727856

SCTP输出

image-20200603171751011